package com.yesep.learn.design.behavioral.chain_of_responsibility.engine;

import java.util.*;

/**
 * 责任链运行上下文
 */
public class ChainContext<R extends IChainRequest> {

    /**
     * 请求数据
     */
    private final R request;
    /**
     * 责任链
     */
    private final IChainHandler<R> handler;
    /**
     * 责任链运行过程数据
     */
    private ChainPayload payload;

    public ChainContext(IChainBuilder<R> builder, ChainPayload payload) {
        this.payload = payload;
        this.request = builder.getRequest();
        this.handler = builder.build();
    }

    public void jump(String key) {
        IChainHandler<R> currentHandler = getCurrentHandler();
        if (Objects.nonNull(currentHandler)) {
            currentHandler.custom(this);
        }
        setHandlerKey(key);
    }

    public void setHandlerKey(String key) {
        getRequest().setHandlerKey(key);
    }

    public void clearHandlerKey() {
        setHandlerKey(null);
    }

    public IChainHandler<R> getChainHandler(String key) {
        if (Objects.isNull(key)) return null;
        IChainHandler<R> currentHandler = handler;
        while (Objects.nonNull(currentHandler)) {
            if (key.equals(currentHandler.getKey())) {
                return currentHandler;
            }
            currentHandler = currentHandler.getNext();
        }
        return null;
    }

    /**
     * @return 当前处理节点
     */
    public IChainHandler<R> getCurrentHandler() {
        String key = request.getHandlerKey();
        return getChainHandler(key);
    }

    /**
     * @return 下一个处理节点
     */
    public IChainHandler<R> getNextHandler() {
        IChainHandler<R> currentHandler = getCurrentHandler();
        return currentHandler != null ? currentHandler.getNext() : null;
    }

    /**
     * @return 上一个处理节点
     */
    public IChainHandler<R> getPreviousHandler() {
        String key = request.getHandlerKey();
        if (Objects.isNull(key)) return null;
        IChainHandler<R> currentHandler = handler;
        IChainHandler<R> previousHandler = null;
        while (Objects.nonNull(currentHandler)) {
            if (key.equals(currentHandler.getKey())) {
                return previousHandler;
            }
            previousHandler = currentHandler;
            currentHandler = currentHandler.getNext();
        }
        return null;
    }

    public R getRequest() {
        return request;
    }

    public IChainHandler<R> getHandler() {
        return handler;
    }

    public ChainPayload getPayload() {
        return payload;
    }

    public void setPayload(ChainPayload payload) {
        this.payload = payload;
    }

}
